From 81aa92fecc298d66eb420468316bcf7a7213171c Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Sun, 30 Nov 2025 17:12:17 +0900
Subject: (김준회) group 기능 추가, 기타 버그 수정, preset 기능추가, 테스트
 페이지 추가
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/[lng]/test/table/page.tsx | 168 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)
 create mode 100644 app/[lng]/test/table/page.tsx

(limited to 'app/[lng]/test/table/page.tsx')

diff --git a/app/[lng]/test/table/page.tsx b/app/[lng]/test/table/page.tsx
new file mode 100644
index 00000000..88d050fc
--- /dev/null
+++ b/app/[lng]/test/table/page.tsx
@@ -0,0 +1,168 @@
+"use client"
+
+import * as React from "react"
+import { ColumnDef } from "@tanstack/react-table"
+import { ClientVirtualTable } from "@/components/client-table/client-virtual-table"
+import { Badge } from "@/components/ui/badge"
+import { Button } from "@/components/ui/button"
+
+// 1. Define the data type
+type TestData = {
+  id: string
+  name: string
+  email: string
+  role: "Admin" | "User" | "Guest"
+  status: "Active" | "Inactive" | "Pending"
+  lastLogin: string
+  amount: number
+}
+
+// 2. Generate dummy data
+const generateData = (count: number): TestData[] => {
+  const roles: TestData["role"][] = ["Admin", "User", "Guest"]
+  const statuses: TestData["status"][] = ["Active", "Inactive", "Pending"]
+  
+  return Array.from({ length: count }).map((_, i) => ({
+    id: `ID-${i + 1}`,
+    name: `User ${i + 1}`,
+    email: `user${i + 1}@example.com`,
+    role: roles[Math.floor(Math.random() * roles.length)],
+    status: statuses[Math.floor(Math.random() * statuses.length)],
+    lastLogin: new Date(Date.now() - Math.floor(Math.random() * 10000000000)).toISOString().split('T')[0],
+    amount: Math.floor(Math.random() * 10000),
+  }))
+}
+
+export default function TestTablePage() {
+  // State for data
+  const [data, setData] = React.useState<TestData[]>([])
+  const [isLoading, setIsLoading] = React.useState(true)
+
+  // Load data on mount
+  React.useEffect(() => {
+    const timer = setTimeout(() => {
+      setData(generateData(100000)) // Generate 1000 rows
+      setIsLoading(false)
+    }, 500)
+    return () => clearTimeout(timer)
+  }, [])
+
+  // 3. Define columns
+  const columns: ColumnDef<TestData>[] = [
+    {
+      accessorKey: "id",
+      header: "ID",
+      size: 80,
+    },
+    {
+      accessorKey: "name",
+      header: "Name",
+      size: 150,
+    },
+    {
+      accessorKey: "email",
+      header: "Email",
+      size: 200,
+    },
+    {
+      accessorKey: "role",
+      header: "Role",
+      size: 100,
+      cell: ({ getValue }) => {
+        const role = getValue() as string
+        return (
+          <Badge variant={role === "Admin" ? "default" : "secondary"}>
+            {role}
+          </Badge>
+        )
+      }
+    },
+    {
+      accessorKey: "status",
+      header: "Status",
+      size: 100,
+      cell: ({ getValue }) => {
+        const status = getValue() as string
+        let color = "bg-gray-500"
+        if (status === "Active") color = "bg-green-500"
+        if (status === "Inactive") color = "bg-red-500"
+        if (status === "Pending") color = "bg-yellow-500"
+        
+        return (
+          <div className="flex items-center gap-2">
+            <div className={`w-2 h-2 rounded-full ${color}`} />
+            <span>{status}</span>
+          </div>
+        )
+      }
+    },
+    {
+      accessorKey: "amount",
+      header: "Amount",
+      size: 200,
+      cell: ({ getValue }) => {
+        const amount = getValue() as number
+        return new Intl.NumberFormat("en-US", {
+          style: "currency",
+          currency: "USD",
+        }).format(amount)
+      },
+      meta: {
+        align: "right"
+      }
+    },
+    {
+      accessorKey: "lastLogin",
+      header: "Last Login",
+      size: 120,
+    },
+    {
+      id: "actions",
+      header: "Actions",
+      size: 100,
+      cell: () => (
+        <Button variant="ghost" size="sm">Edit</Button>
+      ),
+      enablePinning: true,
+    }
+  ]
+
+  return (
+    <div className="h-full flex flex-col p-6 space-y-4">
+      <div className="flex justify-between items-center">
+        <div>
+          <h1 className="text-2xl font-bold tracking-tight">Virtual Table Test</h1>
+          <p className="text-muted-foreground">
+            Testing the ClientVirtualTable component with 1000 generated rows.
+          </p>
+        </div>
+        <div className="flex gap-2">
+            <Button onClick={() => {
+                setIsLoading(true)
+                setTimeout(() => {
+                    setData(generateData(5000))
+                    setIsLoading(false)
+                }, 500)
+            }}>
+                Reload 5k Rows
+            </Button>
+        </div>
+      </div>
+
+      <div className="border rounded-lg overflow-auto h-[1000px]">
+        <ClientVirtualTable
+          data={data}
+          columns={columns}
+          height="100%"
+          isLoading={isLoading}
+          enablePagination={true}
+          enableRowSelection={true}
+          enableGrouping={true}
+          onRowClick={(row) => console.log("Row clicked:", row.original)}
+          enableUserPreset={true}
+          tableKey="test-table"
+        />
+      </div>
+    </div>
+  )
+}
-- 
cgit v1.2.3

